package com.qianfeng.smartmeeting.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qianfeng.smartmeeting.dto.BookingCreateDto;
import com.qianfeng.smartmeeting.entity.Booking;
import com.qianfeng.smartmeeting.entity.Room;
import com.qianfeng.smartmeeting.entity.TimeSlot;
import com.qianfeng.smartmeeting.entity.User;
import com.qianfeng.smartmeeting.exception.BusinessException;
import com.qianfeng.smartmeeting.mapper.BookingMapper;
import com.qianfeng.smartmeeting.mapper.RoomMapper;
import com.qianfeng.smartmeeting.mapper.TimeSlotMapper;
import com.qianfeng.smartmeeting.mapper.UserMapper;
import com.qianfeng.smartmeeting.service.BookingService;
import com.qianfeng.smartmeeting.utils.ResponseResult;
import com.qianfeng.smartmeeting.vo.BookingVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class BookingServiceImpl extends ServiceImpl<BookingMapper, Booking> implements BookingService {

    @Autowired
    private RoomMapper roomMapper;
    
    @Autowired
    private TimeSlotMapper timeSlotMapper;
    
    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional
    public ResponseResult<?> createBooking(BookingCreateDto bookingCreateDto, Long userId) {
        // 1. 验证会议室是否存在且可用
        Room room = roomMapper.selectById(bookingCreateDto.getRoomId());
        if (room == null || room.getStatus() == 0) {
            throw new BusinessException("会议室不存在或不可用");
        }

        // 2. 验证时间段是否存在
        TimeSlot timeSlot = timeSlotMapper.selectById(bookingCreateDto.getSlotId());
        if (timeSlot == null) {
            throw new BusinessException("时间段不存在");
        }

        // 3. 验证预约日期是否有效（最多提前30天）
        LocalDate today = LocalDate.now();
        LocalDate bookingDate = bookingCreateDto.getBookingDate().toInstant()
                .atZone(ZoneId.systemDefault()).toLocalDate();
        
        if (bookingDate.isBefore(today)) {
            throw new BusinessException("预约日期不能是过去日期");
        }
        if (bookingDate.isAfter(today.plusDays(30))) {
            throw new BusinessException("最多只能提前30天预约");
        }

        // 4. 检查时间冲突
        LambdaQueryWrapper<Booking> conflictQuery = new LambdaQueryWrapper<>();
        conflictQuery.eq(Booking::getRoomId, bookingCreateDto.getRoomId())
                   .eq(Booking::getSlotId, bookingCreateDto.getSlotId())
                   .eq(Booking::getBookingDate, bookingCreateDto.getBookingDate())
                   .in(Booking::getStatus, Arrays.asList(0, 1)); // 待确认或已确认状态
        
        if (count(conflictQuery) > 0) {
            throw new BusinessException("该时间段已被预约，请选择其他时间段");
        }

        // 5. 创建预约记录
        Booking booking = new Booking();
        booking.setUserId(userId);
        booking.setRoomId(bookingCreateDto.getRoomId());
        booking.setSlotId(bookingCreateDto.getSlotId());
        booking.setBookingDate(bookingCreateDto.getBookingDate());
        booking.setTitle(bookingCreateDto.getTitle());
        booking.setPurpose(bookingCreateDto.getPurpose());
        
        if (bookingCreateDto.getParticipants() != null && !bookingCreateDto.getParticipants().isEmpty()) {
            booking.setParticipants(JSON.toJSONString(bookingCreateDto.getParticipants()));
        }
        
        booking.setStatus(1); // 直接设置为已确认
        save(booking);

        return ResponseResult.success("预约成功");
    }

    @Override
    public ResponseResult<List<BookingVo>> getUserBookings(Long userId) {
        LambdaQueryWrapper<Booking> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Booking::getUserId, userId)
                   .orderByDesc(Booking::getBookingDate, Booking::getSlotId);
        
        List<Booking> bookings = list(queryWrapper);
        List<BookingVo> bookingVos = convertToBookingVos(bookings);
        
        return ResponseResult.success(bookingVos);
    }

    @Override
    public ResponseResult<List<BookingVo>> getRoomBookings(Long roomId) {
        LambdaQueryWrapper<Booking> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Booking::getRoomId, roomId)
                   .orderByDesc(Booking::getBookingDate, Booking::getSlotId);
        
        List<Booking> bookings = list(queryWrapper);
        List<BookingVo> bookingVos = convertToBookingVos(bookings);
        
        return ResponseResult.success(bookingVos);
    }

    @Override
    @Transactional
    public ResponseResult<?> cancelBooking(Long bookingId, Long userId) {
        Booking booking = getById(bookingId);
        if (booking == null) {
            throw new BusinessException("预约记录不存在");
        }

        // 权限校验：只能取消自己的预约
        if (!booking.getUserId().equals(userId)) {
            throw new BusinessException("只能取消自己的预约");
        }

        // 状态校验
        if (booking.getStatus() == 2) {
            throw new BusinessException("预约已取消，无需重复操作");
        }
        if (booking.getStatus() == 3) {
            throw new BusinessException("已过期的预约不能取消");
        }

        // 时间校验：会议开始前至少1小时才能取消
        TimeSlot timeSlot = timeSlotMapper.selectById(booking.getSlotId());
        if (timeSlot != null) {
            LocalDateTime now = LocalDateTime.now();
            LocalDate bookingDate = booking.getBookingDate().toInstant()
                    .atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDateTime slotStart = LocalDateTime.of(bookingDate, timeSlot.getStartTime().toLocalTime());
            
            if (now.plusHours(1).isAfter(slotStart)) {
                throw new BusinessException("会议开始前1小时内不能取消预约");
            }
        }

        // 更新状态为已取消
        booking.setStatus(2);
        updateById(booking);

        return ResponseResult.success("取消预约成功");
    }

    private List<BookingVo> convertToBookingVos(List<Booking> bookings) {
        List<BookingVo> bookingVos = new ArrayList<>();
        
        for (Booking booking : bookings) {
            BookingVo bookingVo = new BookingVo();
            BeanUtils.copyProperties(booking, bookingVo);
            
            // 设置会议室信息
            Room room = roomMapper.selectById(booking.getRoomId());
            if (room != null) {
                bookingVo.setRoomName(room.getRoomName());
                bookingVo.setLocation(room.getLocation());
                bookingVo.setCapacity(room.getCapacity());
            }
            
            // 设置时间段信息
            TimeSlot timeSlot = timeSlotMapper.selectById(booking.getSlotId());
            if (timeSlot != null) {
                bookingVo.setSlotName(timeSlot.getSlotName());
                bookingVo.setStartTime(timeSlot.getStartTime());
                bookingVo.setEndTime(timeSlot.getEndTime());
            }
            
            // 设置用户信息
            User user = userMapper.selectById(booking.getUserId());
            if (user != null) {
                bookingVo.setUserName(user.getRealName());
                bookingVo.setUserPhone(user.getPhone());
            }
            
            bookingVos.add(bookingVo);
        }
        
        return bookingVos;
    }
}